package com.zhangxin.aiInterview.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.zhangxin.aiInterview.common.ErrorCode;
import com.zhangxin.aiInterview.common.ResultUtils;
import com.zhangxin.aiInterview.exception.BusinessException;
import com.zhangxin.aiInterview.manager.python_api.PythonApi;
import com.zhangxin.aiInterview.manager.xfapi.http.ExtractInterviewQuestionApi;
import com.zhangxin.aiInterview.model.dto.community.SubmitInterviewExperienceCommentRequest;
import com.zhangxin.aiInterview.model.dto.community.SubmitInterviewExperienceRequest;
import com.zhangxin.aiInterview.model.entity.*;
import com.zhangxin.aiInterview.model.vo.response.GetCommonInterviewExperienceListResponse;
import com.zhangxin.aiInterview.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommunityServiceImpl implements CommunityService {
    @Resource
    private UserService userService;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private PositionService positionService;
    @Resource
    private TechFieldService techFieldService;
    @Resource
    private ExtractInterviewQuestionApi extractInterviewQuestionApi;
    @Resource
    private CommonInterviewExperienceService commonInterviewExperienceService;
    @Resource
    private CommonInterviewExperienceCommentService commonInterviewExperienceCommentService;
    @Resource
    private PythonApi pythonApi;
    @Resource
    private AiInterviewTechStackService aiInterviewTechStackService;
    @Resource
    private AiQuestionService aiQuestionService;

    /**
     * 提交面经
     * 
     * @param submitInterviewExperienceRequest
     * @param request
     * @return
     */
    @Override
    public boolean submitInterviewExperience(SubmitInterviewExperienceRequest submitInterviewExperienceRequest,
            HttpServletRequest request) {
        String company = submitInterviewExperienceRequest.getCompany();
        Long techFieldId = submitInterviewExperienceRequest.getTechFieldId();
        Long positionId = submitInterviewExperienceRequest.getPositionId();
        String content = submitInterviewExperienceRequest.getContent();

        // 查询技术领域名称
        TechField techField = techFieldService.getById(techFieldId);
        // 查询岗位名称
        Position position = positionService.getById(positionId);
        String title = company + "-" + techField.getName() + "-" + position.getName() + "面经";

        if (StrUtil.isBlank(title) || StrUtil.isBlank(content))
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "面经标题或面经内容不能为空");

        User user = userService.getLoginUser(request);

        // 提交面经
        CommonInterviewExperience commonInterviewExperience = new CommonInterviewExperience();
        commonInterviewExperience.setTitle(title);
        commonInterviewExperience.setContent(content);
        commonInterviewExperience.setUserId(user.getId());
        commonInterviewExperience.setUserName(user.getUserName());
        commonInterviewExperience.setUserAvatar(user.getUserAvatar());

        boolean save = commonInterviewExperienceService.save(commonInterviewExperience);

        // 异步解析面经内容
        CompletableFuture.runAsync(() -> {
            // 调用大模型提取面经内容
            String questions = extractInterviewQuestionApi.extractInterviewQuestion(content);
            System.out.println(questions);
            questions = questions.replaceAll("^```json\\s*|```\\s*", "");
            List<String> list = JSONUtil.toList(questions, String.class);
            Map<String, List<String>> techStacks = pythonApi.getTechStacks(list);
            log.info("提取到的技术栈: " + techStacks);

            // 将问题和技术栈保存到数据库
            for (Map.Entry<String, List<String>> entry : techStacks.entrySet()) {
                // 获取当前问题标题
                String questionTitle = entry.getKey();
                // 获取该问题对应的技术栈列表
                List<String> techStackList = entry.getValue();

                // 如果技术栈列表为空，则跳过当前问题的处理
                if (techStackList == null || techStackList.isEmpty()) {
                    continue;
                }

                // 一个问题可能对应多个技术栈，遍历技术栈列表
                for (String techStackName : techStackList) {
                    // 使用编程式事务，确保每个"技术栈-问题"对的保存操作是原子的
                    transactionTemplate.execute(status -> {
                        try {
                            // 1. 查找或创建技术栈记录 (ai_interview_tech_stack)
                            AiInterviewTechStack techStack = aiInterviewTechStackService.lambdaQuery()
                                    .eq(AiInterviewTechStack::getCompany, company)
                                    .eq(AiInterviewTechStack::getPositionId, positionId)
                                    .eq(AiInterviewTechStack::getTechStack, techStackName)
                                    .one();

                            // 如果技术栈不存在，则创建它，初始数量为0。
                            // 数量将在确认有新问题添加后才增加。
                            if (techStack == null) {
                                techStack = new AiInterviewTechStack();
                                techStack.setCompany(company);
                                techStack.setTechFieldId(techFieldId);
                                techStack.setPositionId(positionId);
                                techStack.setPosition(position.getName());
                                techStack.setTechStack(techStackName);
                                techStack.setCount(0); // 初始化为0
                                boolean saveResult = aiInterviewTechStackService.save(techStack);
                                if (!saveResult) {
                                    throw new BusinessException(ErrorCode.OPERATION_ERROR, "保存技术栈失败");
                                }
                            }

                            // 2. 检查在当前技术栈下，该问题是否已经存在
                            Long techStackId = techStack.getId();
                            AiQuestion existingQuestion = aiQuestionService.lambdaQuery()
                                    .eq(AiQuestion::getTitle, questionTitle)
                                    .eq(AiQuestion::getTechStackId, techStackId)
                                    .one();

                            // 3. 只有当问题是新的时，才添加问题并更新技术栈计数
                            if (existingQuestion == null) {
                                // 首先，保存新问题
                                AiQuestion newQuestion = new AiQuestion();
                                newQuestion.setTitle(questionTitle);
                                newQuestion.setAnswer(""); // 根据需求，答案字段设置为空字符串
                                newQuestion.setTechStackId(techStackId); // 关联到对应的技术栈ID
                                boolean saveQuestionResult = aiQuestionService.save(newQuestion);
                                if (!saveQuestionResult) {
                                    throw new BusinessException(ErrorCode.OPERATION_ERROR, "保存问题失败");
                                }

                                // 然后，为对应的技术栈数量加1
                                boolean updateResult = aiInterviewTechStackService.lambdaUpdate()
                                        .eq(AiInterviewTechStack::getId, techStackId)
                                        .setSql("count = count + 1")
                                        .update();
                                if (!updateResult) {
                                    throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新技术栈数量失败");
                                }
                            }
                        } catch (Exception e) {
                            // 捕获所有可能的异常
                            log.error("保存技术栈和问题失败", e);
                            // 手动设置事务回滚
                            status.setRollbackOnly();
                            // 向上抛出包装后的业务异常
                            throw new BusinessException(ErrorCode.OPERATION_ERROR, "保存技术栈和问题时发生错误");
                        }
                        // 事务正常完成
                        return true;
                    });
                }
            }
        }).exceptionally(ex -> {
            log.error("异步解析面经内容失败", ex);
            return null;
        });
        return save;
    }

    /**
     * 提交面经评论
     * 
     * @param submitInterviewExperienceCommentRequest
     * @param request
     * @return
     */
    @Override
    public boolean submitInterviewExperienceComment(
            SubmitInterviewExperienceCommentRequest submitInterviewExperienceCommentRequest,
            HttpServletRequest request) {
        String content = submitInterviewExperienceCommentRequest.getContent();
        if (StrUtil.isBlank(content))
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "评论内容不能为空");
        Long interviewExperienceId = submitInterviewExperienceCommentRequest.getInterviewExperienceId();
        if (interviewExperienceId == null)
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "面经id不能为空");
        // 查询用户数据
        User user = userService.getLoginUser(request);
        CommonInterviewExperienceComment commonInterviewExperienceComment = new CommonInterviewExperienceComment();
        commonInterviewExperienceComment.setContent(content);
        commonInterviewExperienceComment.setInterviewExperienceId(interviewExperienceId);
        commonInterviewExperienceComment.setUserId(user.getId());
        commonInterviewExperienceComment.setUserName(user.getUserName());
        commonInterviewExperienceComment.setUserAvatar(user.getUserAvatar());

        // 开启方法事务
        transactionTemplate.execute(status -> {
            // 保存评论数据
            boolean save = commonInterviewExperienceCommentService.save(commonInterviewExperienceComment);
            if (!save)
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "保存评论失败");
            // 更新面经评论数
            boolean update = commonInterviewExperienceService.lambdaUpdate()
                    .eq(CommonInterviewExperience::getId, interviewExperienceId)
                    .setSql("commentCount = commentCount + 1")
                    .update();
            if (!update)
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新面经评论数失败");
            return true;
        });
        return true;
    }

    /**
     * 获取面经列表
     * 
     * @return
     */
    @Override
    public List<GetCommonInterviewExperienceListResponse> getCommonInterviewExperienceList() {
        // 按照创建时间降序排序查询面经
        List<CommonInterviewExperience> commonInterviewExperiences = commonInterviewExperienceService.lambdaQuery()
                .orderByDesc(CommonInterviewExperience::getCreateTime)
                .list();
        List<GetCommonInterviewExperienceListResponse> responseList = commonInterviewExperiences.stream()
                .map(commonInterviewExperience -> {
                    GetCommonInterviewExperienceListResponse result = BeanUtil.copyProperties(commonInterviewExperience,
                            GetCommonInterviewExperienceListResponse.class);
                    // 查询面经评论列表
                    List<CommonInterviewExperienceComment> comments = commonInterviewExperienceCommentService
                            .lambdaQuery()
                            .eq(CommonInterviewExperienceComment::getInterviewExperienceId,
                                    commonInterviewExperience.getId())
                            .list();
                    result.setComments(Collections.emptyList());
                    if (!ObjUtil.isEmpty(comments)) {
                        // 评论不为null
                        List<GetCommonInterviewExperienceListResponse.InterviewExperienceComment> interviewExperienceComments = BeanUtil
                                .copyToList(comments,
                                        GetCommonInterviewExperienceListResponse.InterviewExperienceComment.class);
                        result.setComments(interviewExperienceComments);
                    }
                    return result;
                })
                .collect(Collectors.toList());
        return responseList;
    }
}
